package com.ujs.controller;

import com.ujs.pojo.Log;
import com.ujs.service.LogService;

import org.aspectj.lang.JoinPoint;
;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.Date;

/**
 * @title: LogAop
 * @Author liyunxiao
 * @Date: 2021/1/14 15:02
 */
@Component
@Aspect
public class LogAop {
    private Date visitTime;
    private Class clazz;
    private Method method;
    @Autowired
    private HttpServletRequest httpServletRequest;
    @Autowired
    private LogService logService;
    //前置通知
    @Before("execution(* com.ujs.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime = new Date();//当前时间就是开始访问的时间
        clazz = jp.getTarget().getClass(); //具体要访问的类
        String methodName = jp.getSignature().getName(); //获取访问的方法的名称
        Object[] args = jp.getArgs();//获取访问的方法的参数

        //获取具体执行的方法的Method对象
        if (args == null || args.length == 0) {
            method = clazz.getMethod(methodName); //只能获取无参数的方法
        } else {
            Class[] classArgs = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                if(args[i] instanceof BindingAwareModelMap){
                    //将子类BindingAwareModelMap强转为父类ExtendedModelMap，这个类是Model接口的实现类  clazz.getMethod (methodName, classes); 就不会出现类型转换异常
                    classArgs[i] = Model.class;
                    continue;
                }
                classArgs[i] = args[i].getClass();
            }
            method=clazz.getMethod(methodName, classArgs);
        }
    }

    @After("execution(* com.ujs.controller.*.*(..))")
    public void doAfter(JoinPoint jp){
        long time=new Date().getTime()-visitTime.getTime();
        String url="";
        if(clazz!=null&&method!=null&&clazz!= LogAop.class){

            RequestMapping classAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            if (classAnnotation != null) {
                String []classValue=classAnnotation.value();
                RequestMapping methodRequestMapping = (RequestMapping) method.getAnnotation(RequestMapping.class);
                GetMapping methodGetMapping = (GetMapping) method.getAnnotation(GetMapping.class);
                PostMapping methodPostMapping = (PostMapping) method.getAnnotation(PostMapping.class);
                String []methodValue;
                if (methodRequestMapping != null ) {
                    methodValue=methodRequestMapping.value();
                } else if (methodGetMapping != null) {
                    methodValue=methodGetMapping.value();
                }else {
                    methodValue=methodPostMapping.value();
                }
                url=classValue[0]+methodValue[0];
            }

        }
        //获取ip
        String ip=httpServletRequest.getRemoteAddr();

        //从上下文获得登录的用户
//        SecurityContext context = SecurityContextHolder.getContext();
//        User user =(User) context.getAuthentication().getPrincipal();
//        String username = user.getUsername();
        SecurityContext context = SecurityContextHolder.getContext();//从上下文中获了当前登录的用户
        User user = (User) context.getAuthentication().getPrincipal();
        String username = user.getUsername();
//        String username = getCurrentUsername();

        //将日志相关信息封装
        Log log = new Log();
        log.setExecutionTime(time);
        log.setUserName(username);
        log.setMethod("[类名]"+clazz.getName()+"[方法名]"+method.getName());
        log.setUrl(url);
        log.setVisitTime(visitTime);
        log.setIp(ip);
        logService.save(log);
    }
    public String getCurrentUsername() {

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (principal instanceof UserDetails) {

            return ((UserDetails) principal).getUsername();

        }

        if (principal instanceof Principal) {

            return ((Principal) principal).getName();

        }

        return String.valueOf(principal);

    }

}
